#ifndef ACTION_H_
#define ACTION_H_

#include <stdbool.h>
#include "util/direction.h"
#include "util/rect.h"

#define COOLDOWN_TURN 0
#define COOLDOWN_MOVE TILE_SIZE
#define COOLDOWN_INTERACT 1
#define COOLDOWN_HALT 0
#define COOLDOWN_ATTACK FPS
#define COOLDOWN_TRAVERSE 1
#define COOLDOWN_DIE (12*FPS/10)
#define COOLDOWN_RESPAWN 0

struct Character_t;
struct Monster_t;

typedef enum {
	ACTION_NONE = 0,
	ACTION_TURN,          // actor turns to face a new direction
	ACTION_MOVE,          // actor travels from tile to tile
	ACTION_INTERACT,      // actor interacts with a MapObject
	ACTION_HALT,          // actor stands still
	ACTION_ATTACK_CLOSE,  // actor attacks with close weapon
	ACTION_ATTACK_RANGE,  // actor attacks with ranged weapon
	ACTION_TRAVERSE,      // actor enters teleporters or stairs
	ACTION_DIE,           // actor dies
	ACTION_RESPAWN        // actor respawns
} ActionType;

#if TOWERHACK_DEBUG
#define ACTION_STR(A) ((A)->type == ACTION_NONE         ? "ACTION_NONE" : \
                       (A)->type == ACTION_TURN         ? "ACTION_TURN" : \
                       (A)->type == ACTION_MOVE         ? "ACTION_MOVE" : \
                       (A)->type == ACTION_INTERACT     ? "ACTION_INTERACT" : \
                       (A)->type == ACTION_HALT         ? "ACTION_HALT" : \
                       (A)->type == ACTION_ATTACK_CLOSE ? "ACTION_ATTACK_CLOSE" : \
                       (A)->type == ACTION_ATTACK_RANGE ? "ACTION_ATTACK_RANGE" : \
                       (A)->type == ACTION_TRAVERSE     ? "ACTION_TRAVERSE" : \
                       (A)->type == ACTION_DIE          ? "ACTION_DIE" : \
                       (A)->type == ACTION_RESPAWN      ? "ACTION_RESPAWN" : \
                                                          "[undefined action]")
#endif

typedef struct {
	Direction direction;
} TurnAction;

typedef struct {
	int weapon;
} CloseAttackAction;

typedef struct {
	int weapon;
} RangeAttackAction;

typedef struct {
	Coord target;
} TraverseAction;

typedef struct {
	int target; // map object index
} InteractAction;

typedef struct {
	ActionType type;
	int actor;
	int start_time; // Game time in ticks when this action start(ed)
	int cooldown;
	
	// Coord location; // Where the actor is standing
	// Direction dir;  // Which direction the actor is facing
	
	union {
		TurnAction* turn;
		CloseAttackAction* cattack;
		RangeAttackAction* rattack;
		TraverseAction* traverse;
		InteractAction* interact;
	};
} Action;

#define NO_ACTION(ACTOR) (Action) { ACTION_NONE, (ACTOR), 0, 0, /*{0,0,0},*/ \
                                    /*DIR_NONE,*/ {NULL} }

Action action_alloc_turn (int actor, int start_time, Direction dir);
Action action_alloc_move (int actor, int start_time);
Action action_alloc_interact (int actor, int start_time, int target);
Action action_alloc_halt (int actor, int start_time);
Action action_alloc_closeattack (int actor, int start_time, int weapon);
Action action_alloc_rangeattack (int actor, int start_time, int weapon);
Action action_alloc_traverse (int actor, int start_time, Coord target);
Action action_alloc_die (int actor, int start_time);
Action action_alloc_respawn (int actor, int start_time);
void action_free (Action* a);
bool action_is_equal (const Action* a1, const Action* a2);

#endif
